/******************************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Ltd.                       */
/*                                                                            */
/*  NAME      = ibmmq_core.c                                                  */
/*  NOTE      = IBM MQ协议解析                                                */
/*  DATE      = 2015/06/03 by wuwk                                            */
/******************************************************************************/
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>

#include "frservice_comm.h"
#include "ibmmq_core.h"
#include "ibmmq_analysis.h"
#include "config.h"
#include "cnaps2.h"

#define IBMMQ_REPORT_KEY_CHANEL     APM_REPORT_KEY_SESSION ".mq.channel"
#define IBMMQ_REPORT_KEY_QUEUE      APM_REPORT_KEY_SESSION ".mq.queue"
#define IBMMQ_REPORT_KEY_TOPIC      APM_REPORT_KEY_SESSION ".mq.topic"

extern void *g_p_apm_context;

/*******************************************************************************
*  FUNC     :  释放分片包信息
*  ARGS     :  p_st_fragment (分片包信息)
*  RTN       :  void
*  NOTE     :
*******************************************************************************/
FR_STATIC void __ibmmq_init_fragment(L7_fragment_ibmmq *p_st_fragment)
{
    if (p_st_fragment == NULL)
        return;

    if (p_st_fragment->p_st_data)
       bytebuff_free(&p_st_fragment->p_st_data);

    p_st_fragment->ui_left_head_len = 0;
    p_st_fragment->ui_recv_head_len = 0;
    p_st_fragment->u64_total_len = 0;
    p_st_fragment->u64_left_len = 0;

    memset(p_st_fragment->arr_head, 0x0, sizeof(p_st_fragment->arr_head));

    return;
}

/*******************************************************************************
*  FUNC     :  释放queue链表
*  ARGS     :  p_lst_queue (queue链表)
*  RTN       :  void
*  NOTE     :
*******************************************************************************/
FR_STATIC void __ibmmq_free_lst_queue(Queue_lst_ibmmq *p_lst_queue)
{
    Queue_lst_ibmmq *p_lst_queue_tmp = NULL;
    Queue_lst_ibmmq *p_lst_queue_next = NULL;

    if (p_lst_queue == NULL)
        return;

    p_lst_queue_tmp = p_lst_queue;
    while (p_lst_queue_tmp)
    {
        p_lst_queue_next = p_lst_queue_tmp->next;
        frfree(p_lst_queue_tmp);
        p_lst_queue_tmp = p_lst_queue_next;
    }

    return;
}

/*******************************************************************************
*  FUNC     :  初始化IBM MQ session信息
*  ARGS     :  p_st_session (IBM MQ session信息)
*  RTN      :  FR_FAIL                   失败
*           :  FR_SUCC                   成功
*  NOTE     :
*******************************************************************************/
FR_STATIC int __ibmmq_init_private(L7_session *p_st_session)
{
    L7session_ibmmq_private *p_st_private_session = NULL;
    L7_fragment_ibmmq *p_st_fragment = NULL;
    L7Session_ibmmq *p_st_l7_session = NULL;

    /* 申请整个私有session结构的内存 */
    p_st_private_session = (L7session_ibmmq_private *)frmalloc(sizeof(L7session_ibmmq_private));
    if (p_st_private_session == NULL)
        return FR_FAIL;

    memset(p_st_private_session, 0x00, sizeof(L7session_ibmmq_private));

    /* 申请分片包结构内存 */
    p_st_fragment = (L7_fragment_ibmmq *)frmalloc(sizeof(L7_fragment_ibmmq));
    if (p_st_fragment == NULL)
    {
        frfree(p_st_private_session);
        return FR_FAIL;
    }
    memset(p_st_fragment, 0x00, sizeof(L7_fragment_ibmmq));

    /* 申请session结构体内存 */
    p_st_l7_session = (L7Session_ibmmq *)frmalloc(sizeof(L7Session_ibmmq));
    if (p_st_l7_session == NULL)
    {
        frfree(p_st_private_session);
        frfree(p_st_fragment);
        return FR_FAIL;
    }
    memset(p_st_l7_session, 0x00, sizeof(L7Session_ibmmq));

    p_st_private_session->p_st_fragment = p_st_fragment;
    p_st_private_session->p_st_l7_session = p_st_l7_session;

    p_st_session->p_session_private = p_st_private_session;

    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  释放解析完的数据和分片包
*  ARGS     :  p_st_private(IBM MQ私有数据)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
FR_STATIC void __ibmmq_reset_private(L7session_ibmmq_private *p_st_private)
{
    if (p_st_private == NULL)
        return;

    __ibmmq_init_fragment(p_st_private->p_st_fragment);

    if (p_st_private->p_st_head)
    {
        frfree(p_st_private->p_st_head);
        p_st_private->p_st_head = NULL;
    }

    memset(&(p_st_private->st_trans_info.st_l4_trans), 0x00, sizeof(L4_transaction));

    frreport_body_free(&p_st_private->p_st_data_req);
    frreport_body_free(&p_st_private->p_st_data_resp);

    frreport_body_l7list_free(&p_st_private->p_lst_req);
    frreport_body_l7list_free(&p_st_private->p_lst_mq);

    p_st_private->i_pubsub_flag = IBMMQ_MSG_PTP;
    p_st_private->i_msg_type = 0;

    return;
}

/*******************************************************************************
*  FUNC     :  释放解析完的数据
*  ARGS     :  p_st_private(IBM MQ私有数据)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
FR_STATIC void __ibmmq_reset_analysis_data(L7session_ibmmq_private *p_st_private)
{
    L7_fragment_ibmmq *p_st_fragment = NULL;
    L4_transaction *p_st_l4_trans = NULL;

    if (p_st_private == NULL || p_st_private->p_st_fragment == NULL)
        return;

    p_st_fragment = p_st_private->p_st_fragment;
    bytebuff_rewind(p_st_fragment->p_st_data);

    /* 大数据处理：不清空收包接收时间 */
    p_st_l4_trans = &(p_st_private->st_trans_info.st_l4_trans);
    if (p_st_l4_trans->st_response_time_first_byte.tv_sec == 0)
    {
        p_st_l4_trans->st_request_time.tv_sec = 0;
        p_st_l4_trans->st_request_time.tv_usec = 0;
    }
    p_st_l4_trans->st_response_time.tv_sec = 0;
    p_st_l4_trans->st_response_time.tv_usec = 0;

    frreport_body_free(&p_st_private->p_st_data_req);
    frreport_body_free(&p_st_private->p_st_data_resp);

//    if (p_st_private->p_lst_req)
//        frreport_body_l7list_free(&p_st_private->p_lst_req);
//    if (p_st_private->p_lst_mq)
//        frreport_body_l7list_free(&p_st_private->p_lst_mq);

    p_st_private->i_pubsub_flag = IBMMQ_MSG_PTP;
    p_st_private->i_msg_type = 0;

    return;
}

/*******************************************************************************
*  FUNC     :  IBM MQ session数据添加
*  ARGS     :  p_st_body_data(IBM MQ上报数据)
            :  p_st_l7_session(session数据)
*  RTN      :  FR_FAIL                   失败
*           :  FR_SUCC                   成功
*  NOTE     :
*******************************************************************************/
FR_STATIC int __ibmmq_add_session(Frreport_body_data *p_st_body_data
                                , L7Session_ibmmq *p_st_l7_session
                                , int i_pubsub)
{
    int i_ret = 0;

    if (p_st_body_data == NULL || p_st_l7_session == NULL)
        return FR_FAIL;

    /* 登陆名 */
    if (p_st_l7_session->p_username != NULL)
    {
        i_ret = frreport_body_l7_add_str(p_st_body_data, APM_REPORT_KEY_SESSION_USERNAME, p_st_l7_session->p_username);
        if (i_ret == FR_FAIL)
            return FR_FAIL;
    }

    /* 服务名 */
    if (p_st_l7_session->p_server != NULL)
    {
        i_ret = frreport_body_l7_add_str(p_st_body_data, APM_REPORT_KEY_SESSION_SERVER, p_st_l7_session->p_server);
        if (i_ret == FR_FAIL)
            return FR_FAIL;
    }

    /* 登陆时间 */
    if (p_st_l7_session->st_login.tv_sec != 0 && p_st_l7_session->st_login.tv_usec != 0)
    {
        i_ret = frreport_body_l7_add_timeval(p_st_body_data, APM_REPORT_KEY_SESSION_LOGIN_TIMESTAMP, &p_st_l7_session->st_login);
        if (i_ret == FR_FAIL)
            return FR_FAIL;
    }

    /* 通道名 */
    if (p_st_l7_session->p_chanel != NULL)
    {
        i_ret = frreport_body_l7_add_str(p_st_body_data, IBMMQ_REPORT_KEY_CHANEL, p_st_l7_session->p_chanel);
        if (i_ret == FR_FAIL)
            return FR_FAIL;
    }

    /* 队列名 */
    if (p_st_l7_session->p_queue != NULL)
    {
        if (i_pubsub == IBMMQ_MSG_PTP)
            i_ret = frreport_body_l7_add_str(p_st_body_data, IBMMQ_REPORT_KEY_QUEUE, p_st_l7_session->p_queue);
        else
            i_ret = frreport_body_l7_add_str(p_st_body_data, IBMMQ_REPORT_KEY_TOPIC, p_st_l7_session->p_queue);
        if (i_ret == FR_FAIL)
            return FR_FAIL;
    }

    /* title */
    if (p_st_l7_session->p_title != NULL)
    {
        i_ret = frreport_body_l7_add_str(p_st_body_data, APM_REPORT_KEY_TRANS_TITLE, p_st_l7_session->p_title);
        if (i_ret == FR_FAIL)
            return FR_FAIL;
    }

    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  IBM MQ数据上报
*  ARGS     :  p_st_private(IBM MQ私有数据)
            :  p_st_hash_report(保存Frreport_data)
            :  i_req_resp(请求/响应标记)
*  RTN      :  FR_FAIL                   失败
*           :  FR_SUCC                   成功
*  NOTE     :
*******************************************************************************/
FR_STATIC int __ibmmq_data_report(L7session_ibmmq_private *p_st_private
                                , Conntrack *p_st_conn
                                , Frhash_header *p_st_hash_report
                                , int i_req_resp)
{
    Frreport_data *p_st_report_data = NULL;
    L7_head_ibmmq *p_st_head = NULL;
    L4_transaction *p_st_l4_trans = NULL;

    if (p_st_private == NULL || p_st_private->p_st_head == NULL)
        return FR_FAIL;

    p_st_head = p_st_private->p_st_head;
    if (p_st_head->u32_segm_type != IBMMQ_MQPUT
        && p_st_head->u32_segm_type != IBMMQ_MQPUT1
        && p_st_head->u32_segm_type != IBMMQ_MQPUT_REPLY
        && p_st_head->u32_segm_type != IBMMQ_MQPUT1_REPLY
//        && p_st_head->u32_segm_type != IBMMQ_REQUEST_MSGS
        && p_st_head->u32_segm_type != IBMMQ_ASYNC_MESSAGE
        && p_st_head->u32_segm_type != IBMMQ_MQSUB
        && p_st_head->u32_segm_type != IBMMQ_MQSUB_REPLY
        && p_st_head->u32_segm_type != IBMMQ_MESSAGE
        && p_st_head->u32_segm_type != IBMMQ_MQGET
        && p_st_head->u32_segm_type != IBMMQ_MQGET_REPLY)
    {
//        if (p_st_private->ul_seq > 0 && i_req_resp == IBMMQ_REQUEST)
//            p_st_conn->ul_seq--;

        if (p_st_private->p_st_data_req)
            frreport_body_free(&p_st_private->p_st_data_req);
        if (p_st_private->p_st_data_resp)
            frreport_body_free(&p_st_private->p_st_data_resp);
        return FR_SUCC;
    }

    p_st_l4_trans = &(p_st_private->st_trans_info.st_l4_trans);

    /* request数据上报 */
    if (i_req_resp == IBMMQ_REQUEST)
    {
        if (frreport_body_l7_add_int(p_st_private->p_st_data_req, APM_REPORT_KEY_REQ_ISRESPREQUIRED, p_st_private->i_responserequired) == FR_FAIL)
            goto err;

        /* 保存request数据 */
        p_st_private->p_lst_req = FRREPORT_BODY_L7LIST_CLONE_REQ(p_st_private->p_st_data_req);
        if (p_st_private->p_lst_req == NULL)
            goto err;

        /* 保存mq数据 */
        p_st_private->p_lst_mq = FRREPORT_BODY_L7LIST_CLONE_MQ(p_st_private->p_st_data_req);
        if (p_st_private->p_lst_mq == NULL)
            goto err;

        /* 数据上报 */
        if (p_st_private->i_pubsub_flag == IBMMQ_MSG_SUB)
            p_st_report_data = frreport_data_l7_new(FRREPORT_TYPE_L7DATA_SUB);
        else
            p_st_report_data = frreport_data_l7_new(FRREPORT_TYPE_L7DATA_REQ);
        if (p_st_report_data == NULL)
            goto err;

        /* session信息添加 */
        if (__ibmmq_add_session(p_st_private->p_st_data_req, p_st_private->p_st_l7_session, p_st_private->i_pubsub_flag) == FR_FAIL)
            goto err;

        if (frreport_data_add_body(p_st_report_data, p_st_private->p_st_data_req) == FR_FAIL)
            goto err;
        p_st_private->p_st_data_req = NULL;
        // 解析在IBMMQ层上传输的人行二代支付协议
        cnaps2_parse(p_st_conn, p_st_report_data, p_st_hash_report, FR_YES);
    }
    else  /* response数据上报 */
    {
        if ((p_st_l4_trans->st_request_time_first_byte.tv_sec == 0
            && p_st_l4_trans->st_request_time_first_byte.tv_usec == 0
            && p_st_head->u32_segm_type == IBMMQ_MQGET_REPLY)
            || p_st_head->u32_segm_type == IBMMQ_ASYNC_MESSAGE)
        {
            /* session信息添加 */
            if (__ibmmq_add_session(p_st_private->p_st_data_resp, p_st_private->p_st_l7_session, p_st_private->i_pubsub_flag) == FR_FAIL)
                goto err;
        }

        /* 数据上报 */
        if (p_st_private->i_pubsub_flag == IBMMQ_MSG_NOTIFY)
            p_st_report_data = frreport_data_l7_new(FRREPORT_TYPE_L7DATA_NOTIFY);
        else
            p_st_report_data = frreport_data_l7_new(FRREPORT_TYPE_L7DATA_RESP);
        if (p_st_report_data == NULL)
            goto err;

        if (frreport_data_add_body(p_st_report_data, p_st_private->p_st_data_resp) == FR_FAIL)
            goto err;
        p_st_private->p_st_data_resp = NULL;
        // 解析在IBMMQ层上传输的人行二代支付协议
        cnaps2_parse(p_st_conn, p_st_report_data, p_st_hash_report, FR_NO);
    }
    if (frreport_data_hash(p_st_hash_report, p_st_report_data) == FR_FAIL)
        goto err;
    p_st_report_data = NULL;

    return FR_SUCC;

err:
    if (p_st_private->p_lst_req)
        frreport_body_l7list_free(&p_st_private->p_lst_req);
    if (p_st_private->p_lst_mq)
        frreport_body_l7list_free(&p_st_private->p_lst_mq);
    if (p_st_private->p_st_data_req)
        frreport_body_free(&p_st_private->p_st_data_req);
    if (p_st_private->p_st_data_resp)
        frreport_body_free(&p_st_private->p_st_data_resp);
    frreport_data_free(&p_st_report_data);

    return FR_FAIL;
}

/*******************************************************************************
*  FUNC     :  IBM MQ的请求解析
*  ARGS     :  p_st_private(IBM MQ私有数据)
            :  p_st_conn(入力链接信息)
            :  p_st_hash_report(保存Frreport_data)
            :  p_st_packet(入力packet信息)
*  RTN      :  int
*  NOTE     :
*******************************************************************************/
FR_STATIC int __ibmmq_req_analysis(L7session_ibmmq_private *p_st_private
                                 , Conntrack *p_st_conn
                                 , Frhash_header *p_st_hash_report
                                 , Apm_packet *p_st_packet)
{
    int i_ret = 0;
    unsigned long ul_time_diff = 0;
    L4_transaction *p_st_l4_trans = NULL;
    L7_fragment_ibmmq *p_st_fragment = NULL;

    if (p_st_private == NULL || p_st_private->p_st_fragment == NULL
        || p_st_conn == NULL || p_st_hash_report == NULL || p_st_packet == NULL)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    p_st_fragment = p_st_private->p_st_fragment;
    p_st_l4_trans = &(p_st_private->st_trans_info.st_l4_trans);

    if (frlist_empty(p_st_private->p_lst_req) == FR_NO)
    {
        frreport_body_l7list_free(&p_st_private->p_lst_req);
        frreport_body_l7list_free(&p_st_private->p_lst_mq);
        if (p_st_private->p_st_data_req)
            frreport_body_free(&p_st_private->p_st_data_req);
        memset(p_st_l4_trans, 0x00, sizeof(L4_transaction));
    }

    if (p_st_private->p_st_data_req == NULL)
    {
        p_st_private->p_st_data_req = frreport_body_new_l7(p_st_conn);
        if (p_st_private->p_st_data_req == NULL)
            return APM_L7_ANALYZE_FAIL;
    }

    if (p_st_l4_trans->st_request_time_first_byte.tv_sec == 0
        && p_st_l4_trans->st_request_time_first_byte.tv_usec == 0)
    {
        /* 请求发起的第一个数据包时间 */
        p_st_l4_trans->st_request_time_first_byte.tv_sec = p_st_packet->st_timestamp.tv_sec;
        p_st_l4_trans->st_request_time_first_byte.tv_usec = p_st_packet->st_timestamp.tv_usec;

        p_st_private->ul_seq = frct_seq_increase(p_st_conn);
    }

    if (frreport_body_l7_add_connInfo(p_st_private->p_st_data_req, p_st_conn) == FR_FAIL)
        goto err;

    if (frreport_body_l7_add_ulong(p_st_private->p_st_data_req, APM_REPORT_KEY_REQ_ID, p_st_private->ul_seq) == FR_FAIL)
        goto err;

    if (frreport_body_l7_add_timeval(p_st_private->p_st_data_req, APM_REPORT_KEY_REQ_START_TIMESTAMP, &p_st_l4_trans->st_request_time_first_byte) == FR_FAIL)
        goto err;

    /* 请求结束时间 */
    p_st_l4_trans->st_request_time.tv_sec = p_st_packet->st_timestamp.tv_sec;
    p_st_l4_trans->st_request_time.tv_usec = p_st_packet->st_timestamp.tv_usec;

    if (frreport_body_l7_add_timeval(p_st_private->p_st_data_req, APM_REPORT_KEY_REQ_END_TIMESTAMP, &p_st_packet->st_timestamp) == FR_FAIL)
        goto err;

    /* 请求发送时间 */
    ul_time_diff = frtime_diff(&(p_st_l4_trans->st_request_time_first_byte), &(p_st_l4_trans->st_request_time));
    if (frreport_body_l7_add_ulong(p_st_private->p_st_data_req, APM_REPORT_KEY_REQ_SEND_TIME_US, ul_time_diff) == FR_FAIL)
        goto err;

    /* 请求的字节数 */
    p_st_l4_trans->l_request_bytes = p_st_fragment->u64_total_len;
    if (frreport_body_l7_add_long(p_st_private->p_st_data_req, APM_REPORT_KEY_REQ_DATA_BYTES, p_st_fragment->u64_total_len) == FR_FAIL)
        goto err;

    /* IBM MQ体部数据解析 */
    i_ret = ibmmq_analysis_body(p_st_conn, p_st_packet, p_st_fragment->p_st_data, p_st_private->p_st_data_req, p_st_private, IBMMQ_REQUEST);
    if (i_ret == FR_SUCC)
    {
        /* 数据上报 */
        i_ret = __ibmmq_data_report(p_st_private, p_st_conn, p_st_hash_report, IBMMQ_REQUEST);
        if (i_ret == FR_FAIL)
            goto err;

        return APM_L7_ANALYZE_SET_REQ(APM_L7_ANALYZE_SUCC);
    }
    else if (i_ret == APM_L7_ANALYZE_TODO)
    {
        if (p_st_private->p_st_data_req)
            frreport_body_free(&p_st_private->p_st_data_req);

        return i_ret;
    }

err:
    if (p_st_private->p_st_data_req)
        frreport_body_free(&p_st_private->p_st_data_req);

    return APM_L7_ANALYZE_FAIL;
}

/*******************************************************************************
*  FUNC     :  IBM MQ的响应解析
*  ARGS     :  p_st_private(IBM MQ私有数据)
            :  p_st_conn(入力链接信息)
            :  p_st_hash_report(保存Frreport_data)
            :  p_st_packet(入力packet信息)
*  RTN      :  int
*  NOTE     :
*******************************************************************************/
FR_STATIC int __ibmmq_resp_analysis(L7session_ibmmq_private *p_st_private
                                  , Conntrack *p_st_conn
                                  , Frhash_header *p_st_hash_report
                                  , Apm_packet *p_st_packet)
{
    int i_ret = 0;
    L4_transaction *p_st_l4_trans = NULL;
    L7_fragment_ibmmq *p_st_fragment = p_st_private->p_st_fragment;
    unsigned long ul_time_diff = 0;

    if (p_st_private == NULL || p_st_private->p_st_fragment == NULL
        || p_st_conn == NULL || p_st_hash_report == NULL || p_st_packet == NULL)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    p_st_fragment = p_st_private->p_st_fragment;
    p_st_l4_trans = &(p_st_private->st_trans_info.st_l4_trans);

    if (p_st_private->p_st_data_resp == NULL)
    {
        p_st_private->p_st_data_resp = frreport_body_new_l7(p_st_conn);
        if (p_st_private->p_st_data_resp == NULL)
            return APM_L7_ANALYZE_FAIL;
    }

    if (p_st_l4_trans->st_response_time_first_byte.tv_sec == 0
        && p_st_l4_trans->st_response_time_first_byte.tv_usec == 0)
    {
        /* 响应发起的第一个数据包时间 */
        p_st_l4_trans->st_response_time_first_byte.tv_sec = p_st_packet->st_timestamp.tv_sec;
        p_st_l4_trans->st_response_time_first_byte.tv_usec = p_st_packet->st_timestamp.tv_usec;
    }

    i_ret = frreport_body_l7_add_connInfo(p_st_private->p_st_data_resp, p_st_conn);
    if (i_ret == FR_FAIL)
        goto err;

    /* 有request */
    if (p_st_l4_trans->st_request_time.tv_sec != 0 && p_st_private->p_lst_req != NULL)
    {
        if (FRREPORT_BODY_L7LIST_SET_REQ(p_st_private->p_st_data_resp, &p_st_private->p_lst_req) == FR_FAIL)
            goto err;

        if (p_st_private->p_lst_mq != NULL)
        {
            if (FRREPORT_BODY_L7LIST_SET_MQ(p_st_private->p_st_data_resp, &p_st_private->p_lst_mq) == FR_FAIL)
                goto err;
        }

        ul_time_diff = frtime_diff(&(p_st_l4_trans->st_request_time), &p_st_packet->st_timestamp);
        if (frreport_body_l7_add_ulong(p_st_private->p_st_data_resp, APM_REPORT_KEY_RESP_SERVER_TIME_US, ul_time_diff) == FR_FAIL)
            goto err;

        /* session信息添加 */
        if (__ibmmq_add_session(p_st_private->p_st_data_resp, p_st_private->p_st_l7_session, p_st_private->i_pubsub_flag) == FR_FAIL)
            goto err;
    }

    if (frreport_body_l7_add_timeval(p_st_private->p_st_data_resp, APM_REPORT_KEY_RESP_START_TIMESTAMP, &p_st_l4_trans->st_response_time_first_byte) == FR_FAIL)
        goto err;

    /* 结束时间 */
    p_st_l4_trans->st_response_time.tv_sec = p_st_packet->st_timestamp.tv_sec;
    p_st_l4_trans->st_response_time.tv_usec = p_st_packet->st_timestamp.tv_usec;
    if (frreport_body_l7_add_timeval(p_st_private->p_st_data_resp, APM_REPORT_KEY_RESP_END_TIMESTAMP, &p_st_packet->st_timestamp) == FR_FAIL)
        goto err;

    /* 下载时间 */
    ul_time_diff = frtime_diff(&(p_st_l4_trans->st_response_time_first_byte), &p_st_packet->st_timestamp);
    if (frreport_body_l7_add_ulong(p_st_private->p_st_data_resp, APM_REPORT_KEY_RESP_DOWNLOAD_TIME_US, ul_time_diff) == FR_FAIL)
        goto err;

    /* 响应的字节数 */
    p_st_l4_trans->l_response_bytes = p_st_fragment->u64_total_len;
    if (frreport_body_l7_add_long(p_st_private->p_st_data_resp, APM_REPORT_KEY_RESP_DATA_BYTES, p_st_fragment->u64_total_len) == FR_FAIL)
        goto err;

    /* IBM MQ体部数据解析 */
    i_ret = ibmmq_analysis_body(p_st_conn, p_st_packet, p_st_fragment->p_st_data, p_st_private->p_st_data_resp, p_st_private, IBMMQ_RESPONSE);
    if (i_ret == FR_SUCC)
    {
        /* 数据上报 */
        i_ret = __ibmmq_data_report(p_st_private, p_st_conn, p_st_hash_report, IBMMQ_RESPONSE);
        if (i_ret == FR_FAIL)
            return APM_L7_ANALYZE_FAIL;

        __ibmmq_reset_private(p_st_private);

        return APM_L7_ANALYZE_SET_RESP(APM_L7_ANALYZE_SUCC);
    }
    else if (i_ret == APM_L7_ANALYZE_TODO)
    {
        if (p_st_private->p_st_data_resp)
        {
            if (p_st_private->p_lst_req)
                frreport_body_l7list_free(&p_st_private->p_lst_req);

            /* 保存request数据 */
            p_st_private->p_lst_req = FRREPORT_BODY_L7LIST_CLONE_REQ(p_st_private->p_st_data_resp);
            if (p_st_private->p_lst_req == NULL)
                goto err;

            if (p_st_private->p_lst_mq)
                frreport_body_l7list_free(&p_st_private->p_lst_mq);

            /* 保存mq数据 */
            p_st_private->p_lst_mq = FRREPORT_BODY_L7LIST_CLONE_MQ(p_st_private->p_st_data_resp);
            if (p_st_private->p_lst_mq == NULL)
            {
                frreport_body_l7list_free(&p_st_private->p_lst_req);
                goto err;
            }

            frreport_body_free(&p_st_private->p_st_data_resp);
        }

        return i_ret;
    }

err:
    if (p_st_private->p_st_data_resp)
        frreport_body_free(&p_st_private->p_st_data_resp);

    return APM_L7_ANALYZE_FAIL;
}

/*******************************************************************************
*  FUNC     :  解析体部数据
*  ARGS     :  p_st_private(IBM MQ私有数据)
            :  p_st_conn(入力链接信息)
            :  p_st_hash_report(保存Frreport_data)
            :  p_st_packet(入力packet信息)
*  RTN      :  int
*  NOTE     :
*******************************************************************************/
FR_STATIC int __ibmmq_analysis_data(L7session_ibmmq_private *p_st_private
                                  , Conntrack *p_st_conn
                                  , Frhash_header *p_st_hash_report
                                  , Apm_packet *p_st_packet)
{
    int i_ret = 0;
    uint32_t u32_segm_type = 0;
    L7_head_ibmmq *p_st_head = NULL;

    if (p_st_private == NULL || p_st_private->p_st_head == NULL)
        return APM_L7_ANALYZE_FAIL;

    p_st_head = p_st_private->p_st_head;
    u32_segm_type = p_st_head->u32_segm_type;

    /* request */
    if (p_st_packet->i_direction == FR_DIRECT_CLIENT2SRV)
    {
        if ((u32_segm_type >= IBMMQ_MQCONN && u32_segm_type <= IBMMQ_MQSUBRQ)
            || (u32_segm_type >= IBMMQ_XA_START && u32_segm_type <= IBMMQ_XA_COMPLETE)
            || u32_segm_type == IBMMQ_INITIAL
            || u32_segm_type == IBMMQ_HEARTBEAT
            || u32_segm_type == IBMMQ_CONAUTH_INFO
            || u32_segm_type == IBMMQ_REQUEST_MSGS)
        {
            p_st_private->i_responserequired = 1;
        }
        else
        {
            p_st_private->i_responserequired = 0;
        }

        i_ret = __ibmmq_req_analysis(p_st_private, p_st_conn, p_st_hash_report, p_st_packet);
    }
    else
    {
        i_ret = __ibmmq_resp_analysis(p_st_private, p_st_conn, p_st_hash_report, p_st_packet);
    }

    return i_ret;
}

/*******************************************************************************
*  FUNC     :  取得完整的数据包并解析
*  ARGS     :  p_st_private(IBM MQ私有数据)
            :  p_st_conn(入力链接信息)
            :  p_st_hash_report(保存Frreport_data)
            :  p_st_packet(入力packet信息)
*  RTN      :  int
*  NOTE     :
*******************************************************************************/
FR_STATIC int __ibmmq_getdata_analysis(L7session_ibmmq_private *p_st_private
                                      , Conntrack *p_st_conn
                                      , Frhash_header *p_st_hash_report
                                      , Apm_packet *p_st_packet
                                      , char *p_data
                                      , unsigned int ui_data_len)
{
    L7_fragment_ibmmq *p_st_fragment = NULL;
    L7_head_ibmmq *p_st_head = NULL;
    unsigned int ui_left_len = 0;
    unsigned int ui_head_len = 0;
    unsigned int ui_left_head_len = 0;
    int i_data_left_flg = 0;
    int i_append_head = 0;
    int i_ret = 0;

    if (p_st_private == NULL || p_st_private->p_st_fragment == NULL
        || p_st_packet == NULL || p_st_packet->p_payload == NULL)
        return APM_L7_ANALYZE_FAIL;

    p_st_fragment = p_st_private->p_st_fragment;
    if (ui_data_len == 0)
        return APM_L7_ANALYZE_TODO;

    /* 上一次的头数据包未完全解析，继续解析头数据 */
    if (p_st_fragment->ui_recv_head_len)
    {
        /* 上一次的头数据加本次数据长度小于4 */
        if (p_st_fragment->ui_recv_head_len + ui_data_len < IBMMQ_TSHx_LEN)
        {
            memcpy(p_st_fragment->arr_head + p_st_fragment->ui_recv_head_len
                 , p_data, ui_data_len);
            p_st_fragment->ui_recv_head_len += ui_data_len;
            return APM_L7_ANALYZE_TODO;
        }
        /* 上一次的头数据不到4 */
        if (p_st_fragment->ui_recv_head_len < IBMMQ_TSHx_LEN)
        {
            /* 剩余StructID的长度 */
            ui_left_head_len = IBMMQ_TSHx_LEN - p_st_fragment->ui_recv_head_len;
            memcpy(p_st_fragment->arr_head + p_st_fragment->ui_recv_head_len
                 , p_data, ui_left_head_len);
            /* StructID为TSHM */
            if (strncmp(p_st_fragment->arr_head, IBMMQ_STR_TSHM, IBMMQ_TSHx_LEN) == 0)
                ui_head_len = IBMMQ_HEAD_LEN_TSHM;
            else if (strncmp(p_st_fragment->arr_head, IBMMQ_STR_TSH, IBMMQ_TSH_LEN) == 0)
                ui_head_len = IBMMQ_HEAD_LEN_TSH;
            else
                goto err;

            /* 不够头部数据 */
            if (ui_data_len + p_st_fragment->ui_recv_head_len < ui_head_len)
            {
                memcpy(p_st_fragment->arr_head + IBMMQ_TSHx_LEN
                     , p_data+ui_left_head_len, ui_data_len-ui_left_head_len);
                p_st_fragment->ui_recv_head_len += ui_data_len;
                return APM_L7_ANALYZE_TODO;
            }
            memcpy(p_st_fragment->arr_head + IBMMQ_TSHx_LEN
                 , p_data+ui_left_head_len, ui_head_len - IBMMQ_TSHx_LEN);
        }
        else
        {
            if (strncmp(p_st_fragment->arr_head, IBMMQ_STR_TSHM, IBMMQ_TSHx_LEN) == 0)
            {
                ui_left_head_len = IBMMQ_HEAD_LEN_TSHM - p_st_fragment->ui_recv_head_len;
                /* 不够头部数据 */
                if (ui_data_len < ui_left_head_len)
                {
                    memcpy(p_st_fragment->arr_head + p_st_fragment->ui_recv_head_len
                         , p_data, ui_data_len);
                    p_st_fragment->ui_recv_head_len += ui_data_len;
                    return APM_L7_ANALYZE_TODO;
                }

                memcpy(p_st_fragment->arr_head + p_st_fragment->ui_recv_head_len
                     , p_data, ui_left_head_len);
                ui_head_len = IBMMQ_HEAD_LEN_TSHM;
            }
            else if (strncmp(p_st_fragment->arr_head, IBMMQ_STR_TSH, IBMMQ_TSH_LEN) == 0)
            {
                ui_left_head_len = IBMMQ_HEAD_LEN_TSH - p_st_fragment->ui_recv_head_len;
                /* 不够头部数据 */
                if (ui_data_len < ui_left_head_len)
                {
                    memcpy(p_st_fragment->arr_head + p_st_fragment->ui_recv_head_len
                            , p_data, ui_data_len);
                    p_st_fragment->ui_recv_head_len += ui_data_len;
                    return APM_L7_ANALYZE_TODO;
                }

                memcpy(p_st_fragment->arr_head + p_st_fragment->ui_recv_head_len
                     , p_data, ui_left_head_len);
                ui_head_len = IBMMQ_HEAD_LEN_TSH;
            }
            else
            {
                goto err;
            }
        }

        /* 解析头部数据 */
        i_ret = ibmmq_analysis_head(p_st_fragment->arr_head, ui_head_len, &p_st_head);
        if (i_ret != FR_SUCC)
            goto err;

        ui_data_len -= ui_left_head_len;
        p_data += ui_left_head_len;
        p_st_fragment->u64_total_len = p_st_head->ui_msg_len;
        p_st_fragment->u64_left_len = p_st_fragment->u64_total_len - ui_head_len;
        p_st_private->p_st_head = p_st_head;

        p_st_fragment->ui_left_head_len = 0;
        p_st_fragment->ui_recv_head_len = 0;
        memset(p_st_fragment->arr_head, 0x00, sizeof(p_st_fragment->arr_head));

        i_append_head = 1;
    }

    /* 上次packet还遗留的数据长度 */
    ui_left_len = p_st_fragment->u64_left_len;

    /* 创建bytebuffer */
    if (p_st_fragment->p_st_data == NULL)
    {
        /* 做成bytebuffer */
        p_st_fragment->p_st_data = bytebuff_creat();
        if (p_st_fragment->p_st_data == NULL)
            goto err;
    }

    /* 上次的数据包不完整 */
    if (ui_left_len && (strncmp(p_data, IBMMQ_STR_TSH, IBMMQ_TSH_LEN) != 0 || i_append_head == 1))
    {
        /* 消息分片包，带有ibmmq头部 */
        if (p_st_private->ui_left_msgfragment_len != 0)
        {
            if (p_st_private->p_st_head == NULL)
                goto err;
            /* 去掉头部 */
            p_data += p_st_private->p_st_head->ui_head_len;
            ui_data_len -= p_st_private->p_st_head->ui_head_len;
            p_st_fragment->u64_left_len -= p_st_private->p_st_head->ui_head_len;
        }

        /* 本次数据还不够 */
        if (ui_left_len > ui_data_len)
        {
            if (ui_data_len != 0)
            {
                /* 将本次数据存入buffer */
                i_ret = bytebuff_add(p_st_fragment->p_st_data, p_data, ui_data_len);
                if (i_ret != FR_SUCC)
                    goto err;
                p_st_fragment->u64_left_len -= ui_data_len;
            }
        }
        else
        {
            /* 将剩余需要的数据存入buffer */
            i_ret = bytebuff_add(p_st_fragment->p_st_data, p_data, ui_left_len);
            if (i_ret != FR_SUCC)
                goto err;
            p_st_fragment->u64_left_len = 0;
            /* 数据包内还有数据 */
            if (ui_left_len < ui_data_len)
            {
                i_data_left_flg = 1;
                ui_data_len -= ui_left_len;
                p_data += ui_left_len;
            }
        }

        if (p_st_fragment->p_st_data->ui_skip_len != 0)
            return APM_L7_ANALYZE_TODO;

        p_st_private->ui_left_msgfragment_len = 0;

        /* 解析当前体数据 */
        i_ret = __ibmmq_analysis_data(p_st_private, p_st_conn, p_st_hash_report, p_st_packet);
        if (i_ret == APM_L7_ANALYZE_FAIL)
            goto err;
        else if (i_ret == APM_L7_ANALYZE_TODO)
        {
            __ibmmq_reset_analysis_data(p_st_private);
            p_st_fragment->ui_left_head_len = 0;
            p_st_fragment->ui_recv_head_len = 0;

            /* 后面还有分片的消息内容 */
            if (p_st_private->ui_left_msgfragment_len != 0)
            {
                if (p_st_private->i_msgfragment_flag == 1)
                    /* 消息内容长度+ibm mq的头部长度 */
                    p_st_fragment->u64_left_len = p_st_private->ui_left_msgfragment_len + p_st_private->p_st_head->ui_head_len;
                else
                    p_st_fragment->u64_left_len = p_st_private->ui_left_msgfragment_len;

                p_st_private->i_msgfragment_flag = 0;

                if (i_data_left_flg == 1)
                {
                    i_ret = __ibmmq_getdata_analysis(p_st_private, p_st_conn, p_st_hash_report
                                               , p_st_packet, p_data, ui_data_len);
                    if (i_ret == APM_L7_ANALYZE_FAIL)
                        goto err;
                    return i_ret;
                }
            }
            return APM_L7_ANALYZE_TODO;
        }
        else
        {
            frfree(p_st_private->p_st_head);
            p_st_private->p_st_head = NULL;
            if (p_st_fragment->p_st_data)
                bytebuff_free(&p_st_fragment->p_st_data);
            p_st_fragment->u64_total_len = 0;
            p_st_fragment->ui_left_head_len = 0;
            p_st_fragment->ui_recv_head_len = 0;

            return i_ret;
        }
    }
    else
    {
        if (strncmp(p_data, IBMMQ_STR_TSH, IBMMQ_TSH_LEN) != 0)
            goto err;
    }

    /* 上次的数据包完整，开始新的数据包解析 */
    /* 数据长度小于4，无法取得StructID */
    if (ui_data_len < IBMMQ_TSHx_LEN)
    {
        p_st_fragment->ui_recv_head_len = ui_data_len;
        memcpy(p_st_fragment->arr_head, p_data, ui_data_len);
        return APM_L7_ANALYZE_TODO;
    }
    /* 取得IBM MQ头部长度 */
    if (strncmp(p_data, IBMMQ_STR_TSHM, IBMMQ_TSHx_LEN) == 0)
        ui_head_len = IBMMQ_HEAD_LEN_TSHM;
    else
        ui_head_len = IBMMQ_HEAD_LEN_TSH;

    /* 数据长度不够IBM MQ头部长度 */
    if (ui_data_len < ui_head_len)
    {
        p_st_fragment->ui_left_head_len = ui_head_len - ui_data_len;
        p_st_fragment->ui_recv_head_len = ui_data_len;
        memcpy(p_st_fragment->arr_head, p_data, ui_data_len);
        return APM_L7_ANALYZE_TODO;
    }

    /* 解析头部数据 */
    i_ret = ibmmq_analysis_head(p_data, ui_head_len, &p_st_head);
    if (i_ret != FR_SUCC)
        goto err;

    ui_data_len -= ui_head_len;
    p_data += ui_head_len;
    p_st_fragment->u64_total_len = p_st_head->ui_msg_len;
    if (p_st_private->p_st_head)
        frfree(p_st_private->p_st_head);
    p_st_private->p_st_head = p_st_head;

    /* 数据长度不够 */
    if (p_st_fragment->u64_total_len > ui_data_len + ui_head_len)
    {
        if (ui_data_len != 0)
        {
            i_ret = bytebuff_add(p_st_fragment->p_st_data, p_data, ui_data_len);
            if (i_ret != FR_SUCC)
                goto err;
        }
        p_st_fragment->u64_left_len = p_st_fragment->u64_total_len - ui_data_len - ui_head_len;
    }
    else
    {
        i_ret = bytebuff_add(p_st_fragment->p_st_data, p_data, p_st_fragment->u64_total_len - ui_head_len);
        if (i_ret != FR_SUCC)
            goto err;
        p_st_fragment->u64_left_len = 0;

        /* 数据包内还有数据 */
        if (p_st_fragment->u64_total_len < ui_data_len + ui_head_len)
        {
            i_data_left_flg = 1;
            ui_data_len -= p_st_fragment->u64_total_len;
            p_data += p_st_fragment->u64_total_len;
        }
    }

    p_st_private->ui_left_msgfragment_len = 0;

    /* 解析体数据 */
    i_ret = __ibmmq_analysis_data(p_st_private, p_st_conn, p_st_hash_report, p_st_packet);
    if (i_ret == APM_L7_ANALYZE_FAIL)
        goto err;
    else if (i_ret == APM_L7_ANALYZE_TODO)
    {
        __ibmmq_reset_analysis_data(p_st_private);
        p_st_fragment->ui_left_head_len = 0;
        p_st_fragment->ui_recv_head_len = 0;

        /* 后面还有分片的消息内容 */
        if (p_st_private->ui_left_msgfragment_len != 0)
        {
            if (p_st_private->i_msgfragment_flag == 1)
                /* 消息内容长度+ibm mq的头部长度 */
                p_st_fragment->u64_left_len = p_st_private->ui_left_msgfragment_len + p_st_private->p_st_head->ui_head_len;
            else
                p_st_fragment->u64_left_len = p_st_private->ui_left_msgfragment_len;

            p_st_private->i_msgfragment_flag = 0;

            if (i_data_left_flg == 1)
            {
                i_ret = __ibmmq_getdata_analysis(p_st_private, p_st_conn, p_st_hash_report
                                               , p_st_packet, p_data, ui_data_len);
                if (i_ret == APM_L7_ANALYZE_FAIL)
                   goto err;
                return i_ret;
            }
        }

        return APM_L7_ANALYZE_TODO;
    }
    else
    {
        frfree(p_st_private->p_st_head);
        p_st_private->p_st_head = NULL;
        if (p_st_fragment->p_st_data)
            bytebuff_free(&p_st_fragment->p_st_data);
        p_st_fragment->u64_total_len = 0;
        p_st_fragment->ui_left_head_len = 0;
        p_st_fragment->ui_recv_head_len = 0;

        return i_ret;
    }

err:
    __ibmmq_reset_private(p_st_private);
    return APM_L7_ANALYZE_FAIL;
}

/*******************************************************************************
*  FUNC     :  私有信息销毁
*  ARGS     :  p_private_session(IBM MQ的私有session数据)
*  RTN      :  int
*  NOTE     :
*******************************************************************************/
int ibmmq_session_destroy(void *p_private_session)
{
    L7session_ibmmq_private *p_st_private;
    L7Session_ibmmq *p_st_l7_session;

    /* 判断session是否为空 */
    if (p_private_session == NULL)
        return FR_SUCC;

    p_st_private = (L7session_ibmmq_private *)p_private_session;

    /* 销毁分片包数据 */
    if (p_st_private->p_st_fragment)
    {
        /* 销毁分片包内的packet数据 */
        __ibmmq_init_fragment(p_st_private->p_st_fragment);
        frfree(p_st_private->p_st_fragment);
    }

    /* 销毁头数据 */
    if (p_st_private->p_st_head)
        frfree(p_st_private->p_st_head);

    if (p_st_private->p_st_l7_session)
    {
        p_st_l7_session = p_st_private->p_st_l7_session;
        if (p_st_l7_session->p_username)
            frfree(p_st_l7_session->p_username);
        if (p_st_l7_session->p_server)
            frfree(p_st_l7_session->p_server);
        if (p_st_l7_session->p_chanel)
            frfree(p_st_l7_session->p_chanel);
        if (p_st_l7_session->p_queue)
            frfree(p_st_l7_session->p_queue);
        if (p_st_l7_session->p_title)
            frfree(p_st_l7_session->p_title);
        if (p_st_l7_session->p_lst_queue)
            __ibmmq_free_lst_queue(p_st_l7_session->p_lst_queue);
        frfree(p_st_private->p_st_l7_session);
    }

    frreport_body_free(&p_st_private->p_st_data_req);
    frreport_body_free(&p_st_private->p_st_data_resp);

    frreport_body_l7list_free(&p_st_private->p_lst_req);
    frreport_body_l7list_free(&p_st_private->p_lst_mq);

    frfree(p_st_private);

    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  判断当前数据链路是否是ibmmq协议
*  ARGS     :  p_st_conn(入力链接信息)
*           :  p_st_packet(入力数据包)
*  RTN      :  APM_L7_IS_NO   (NO)
*              APM_L7_IS_YES  (YES)
*  NOTE     :
*******************************************************************************/
int ibmmq_detect(Conntrack *p_st_conn, Apm_packet *p_st_packet)
{
    char *p_payload = NULL;
    char arr_len[5];
    unsigned char *p_payload_tmp = NULL;
    unsigned int ui_len = 0;
    unsigned int ui_seg_len = 0;
    uint32_t u32_segm_type = 0;
    uint32_t *p_u32_len = NULL;
    int i_index = 0;
    int i_ret = 0;

    if (p_st_conn == NULL || p_st_packet == NULL || p_st_packet->p_payload == NULL)
        return APM_L7_IS_NO;

    p_payload = p_st_packet->p_payload;
    p_payload_tmp = (unsigned char *)p_payload;
    ui_len = p_st_packet->ui_payload_len;

    if (ui_len < 4)
        goto end;

    if (strncmp(p_payload, IBMMQ_STR_TSH, IBMMQ_TSH_LEN) != 0)
        goto end;

    /* 数据包长度判断 */
    if (ui_len > 8)
    {
         memcpy(arr_len, p_payload + 4, 4);
         arr_len[4] = '\0';
         p_u32_len = (uint32_t *)arr_len;
         ui_seg_len = ntohl(*p_u32_len);
         /* 消息的最大长度100M */
         if (ui_seg_len  > IBMMQ_LEN_M*100)
            goto end;
    }
    else
        goto end;

    /* 方向明确 */
    if (frct_get_direct_known(p_st_conn) == FR_DIRECT_KNOWN)
    {
        frservice_add(g_p_apm_context, MODULE_L7PROTO, p_st_packet->dst_ip, p_st_packet->dst_port, NULL, 0);
        return APM_L7_IS_YES;
    }

    /* 方向不明确 */
    /* 取SegmType值判断消息类型 */
    if (strncmp(p_payload, IBMMQ_STR_TSHM, IBMMQ_TSHx_LEN) == 0)
        i_index = 17;
    else
        i_index = 9;

    if ((int)ui_len > i_index)
    {
        u32_segm_type = p_payload_tmp[i_index];
        if ((u32_segm_type >= IBMMQ_MQCONN && u32_segm_type <= IBMMQ_MQSUBRQ)
            || (u32_segm_type >= IBMMQ_XA_START && u32_segm_type <= IBMMQ_XA_COMPLETE)
            || u32_segm_type == IBMMQ_USERID
            || u32_segm_type == IBMMQ_MESSAGE)
        {
             i_ret = frcap_set_cs_srv(p_st_conn, p_st_packet->dst_ip, p_st_packet->dst_port);
            if (i_ret != FR_SUCC)
            {
                frdbg("frcap_set_cs_srv failed\n");
                return APM_L7_IS_NO;
            }
            frservice_add(g_p_apm_context, MODULE_L7PROTO, p_st_packet->dst_ip, p_st_packet->dst_port, NULL, 0);
            p_st_conn->flg_direct_known = FR_DIRECT_KNOWN;
            return APM_L7_IS_YES;
        }
        else if ((u32_segm_type >= IBMMQ_MQCONN_REPLY && u32_segm_type <= IBMMQ_MQSUBRQ_REPLY)
            || (u32_segm_type >= IBMMQ_XA_START_REPLY && u32_segm_type <= IBMMQ_XA_COMPLETE_REPLY))
        {
            i_ret = frcap_set_cs_srv(p_st_conn, p_st_packet->src_ip, p_st_packet->src_port);
            if (i_ret != FR_SUCC)
            {
                frdbg("frcap_set_cs_srv failed\n");
                return APM_L7_IS_NO;
            }
            frservice_add(g_p_apm_context, MODULE_L7PROTO, p_st_packet->dst_ip, p_st_packet->dst_port, NULL, 0);
            return APM_L7_IS_YES;
        }
    }

end:
    /* 长度为0的数据不进行识别协议查询 */
    if (ui_len == 0)
        return APM_L7_IS_NO;

    if (frct_get_direct_known(p_st_conn) == FR_DIRECT_UNKNOWN)
    {
        i_ret = frservice_get(g_p_apm_context, MODULE_L7PROTO, p_st_packet->dst_ip, p_st_packet->dst_port, NULL, 0, NULL);
        if (i_ret == FR_SUCC)
        {
            frcap_set_cs_srv(p_st_conn, p_st_packet->dst_ip, p_st_packet->dst_port);
            return APM_L7_IS_YES;
        }
        i_ret = frservice_get(g_p_apm_context, MODULE_L7PROTO, p_st_packet->src_ip, p_st_packet->src_port, NULL, 0, NULL);
        if (i_ret == FR_SUCC)
        {
            frcap_set_cs_srv(p_st_conn, p_st_packet->src_ip, p_st_packet->src_port);
            return APM_L7_IS_YES;
        }
    }
    else
    {
        i_ret = frservice_get(g_p_apm_context, MODULE_L7PROTO, p_st_packet->dst_ip, p_st_packet->dst_port, NULL, 0, NULL);
        if (i_ret == FR_SUCC)
            return APM_L7_IS_YES;
    }
    return APM_L7_IS_NO;
}

/*******************************************************************************
*  FUNC     :  IBM MQ的packet解析
*  ARGS     :  p_st_conn(入力链接信息)
            :  p_st_packet(入力packet信息)
            :  p_st_hash_report(保存Frreport_data)
*  RTN      :  参照module.h
*  NOTE     :
*******************************************************************************/
int ibmmq_analysis(Conntrack *p_st_conn
                  , Apm_packet *p_st_packet
                  , Frhash_header *p_st_hash_report)
{
    L7session_ibmmq_private *p_st_private = NULL;
    L7_session *p_st_session = NULL;
    int i_ret = 0;

    if (p_st_conn == NULL || p_st_packet == NULL
         || p_st_hash_report == NULL)
         return APM_L7_ANALYZE_FAIL;

    /* 到Conntrack中取得session信息 */
    p_st_session = frct_get_session(p_st_conn);
    if (p_st_session == NULL)
        return APM_L7_ANALYZE_FAIL;

#if APM_CNAPS2_DBG
    CNAPS2_PRINT_TIMEVAL("PacketIn", p_st_packet->st_timestamp);
    char arr_ip_src[56], arr_ip_dst[56];
    snprintf(arr_ip_src, sizeof(arr_ip_src), "%s", int_ntoa(p_st_packet->src_ip));
    snprintf(arr_ip_dst, sizeof(arr_ip_src), "%s", int_ntoa(p_st_packet->dst_ip));
    CNAPS2_PRINT_DBG("Src:[%s:%d] Dest:[%s:%d]\n", arr_ip_src, p_st_packet->src_port, arr_ip_dst, p_st_packet->dst_port);
#endif

    /*
    * 如果入力p_st_packet是FIN包, 说明本次IBM MQ的connection结束,
    * 释放本次session信息. 如果入力p_st_packet是SYN包,说明新的IBM MQ的
    * connection开始了, 释放上次可能残留的session信息
    */
    if (p_st_packet->em_analyz_cmd == FRANALYZ_CMD_FIN
        || p_st_packet->em_analyz_cmd == FRANALYZ_CMD_SYN)
    {
        /* 销毁所有相关本次IBM MQ的connection的数据 */
        ibmmq_session_destroy((void *)(p_st_session->p_session_private));
        p_st_session->p_session_private = NULL;
        return APM_L7_ANALYZE_SUCC;
    }

     /* 本次链路的第一个有效packet包,创建链路 */
    if (p_st_session->p_session_private == NULL)
    {
        /* 初始化IBM MQ的私有数据 */
        i_ret = __ibmmq_init_private(p_st_session);
        if (i_ret != FR_SUCC)
            return APM_L7_ANALYZE_FAIL;

        /* 设置session ID */
        fruuid(p_st_session->arr_session_id);
    }

    p_st_private = (L7session_ibmmq_private *)p_st_session->p_session_private;

    i_ret = __ibmmq_getdata_analysis(p_st_private
                                  , p_st_conn
                                  , p_st_hash_report
                                  , p_st_packet
                                  , p_st_packet->p_payload
                                  , p_st_packet->ui_payload_len);
    return i_ret;
}
